<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>交互式成绩分析工具</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js"></script>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
        }
        
        body {
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            min-height: 100vh;
            padding: 20px;
        }
        
        .container {
            max-width: 1400px;
            margin: 0 auto;
            background: rgba(255, 255, 255, 0.95);
            border-radius: 20px;
            box-shadow: 0 20px 40px rgba(0, 0, 0, 0.2);
            overflow: hidden;
        }
        
        header {
            background: linear-gradient(135deg, #5e72e4 0%, #825ee4 100%);
            color: white;
            padding: 30px;
            text-align: center;
            position: relative;
        }
        
        header h1 {
            font-size: 2.5rem;
            margin-bottom: 10px;
            text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
        }
        
        header p {
            font-size: 1.1rem;
            opacity: 0.9;
        }
        
        .header-row-setting {
            position: absolute;
            top: 20px;
            right: 30px;
            background: rgba(255, 255, 255, 0.2);
            padding: 8px 15px;
            border-radius: 20px;
            display: flex;
            align-items: center;
            gap: 8px;
            backdrop-filter: blur(10px);
        }
        
        .header-row-setting label {
            font-size: 0.9rem;
            font-weight: 600;
        }
        
        .header-row-setting input {
            width: 60px;
            padding: 4px 8px;
            border: 1px solid rgba(255, 255, 255, 0.3);
            border-radius: 6px;
            background: rgba(255, 255, 255, 0.9);
            font-size: 0.9rem;
        }
        
        main {
            padding: 30px;
        }
        
        .step-indicator {
            display: flex;
            justify-content: center;
            margin-bottom: 30px;
            gap: 20px;
        }
        
        .step {
            display: flex;
            align-items: center;
            gap: 10px;
            padding: 10px 20px;
            background: #f0f2f5;
            border-radius: 30px;
            font-weight: 600;
            color: #718096;
            transition: all 0.3s ease;
        }
        
        .step.active {
            background: linear-gradient(135deg, #5e72e4 0%, #825ee4 100%);
            color: white;
            transform: scale(1.05);
        }
        
        .step.completed {
            background: #48bb78;
            color: white;
        }
        
        .step-number {
            width: 30px;
            height: 30px;
            border-radius: 50%;
            background: rgba(255, 255, 255, 0.3);
            display: flex;
            align-items: center;
            justify-content: center;
            font-weight: bold;
        }
        
        .file-upload {
            background: #f8f9fe;
            border: 2px dashed #d1d5db;
            border-radius: 15px;
            padding: 40px;
            text-align: center;
            margin-bottom: 30px;
            transition: all 0.3s ease;
        }
        
        .file-upload:hover {
            border-color: #5e72e4;
            background: #f0f2ff;
        }
        
        .file-upload input[type="file"] {
            display: none;
        }
        
        .file-upload label {
            display: inline-block;
            background: linear-gradient(135deg, #5e72e4 0%, #825ee4 100%);
            color: white;
            padding: 12px 30px;
            border-radius: 50px;
            cursor: pointer;
            font-weight: 600;
            transition: all 0.3s ease;
            box-shadow: 0 4px 15px rgba(94, 114, 228, 0.3);
        }
        
        .file-upload label:hover {
            transform: translateY(-2px);
            box-shadow: 0 6px 20px rgba(94, 114, 228, 0.4);
        }
        
        .file-name {
            margin-top: 15px;
            font-weight: 600;
            color: #4a5568;
        }
        
        .config-section {
            background: #f8f9fe;
            border-radius: 15px;
            padding: 25px;
            margin-bottom: 30px;
        }
        
        .part-selector {
            display: flex;
            gap: 15px;
            margin-bottom: 20px;
            flex-wrap: wrap;
        }
        
        .part-tab {
            padding: 10px 20px;
            border-radius: 10px 10px 0 0;
            background: #e2e8f0;
            color: #4a5568;
            cursor: pointer;
            font-weight: 600;
            transition: all 0.3s ease;
            border: 2px solid transparent;
        }
        
        .part-tab.active {
            background: white;
            color: #2d3748;
            border-color: #cbd5e0;
            border-bottom-color: white;
            transform: translateY(-2px);
        }
        
        .part-control-btn {
            width: 36px;
            height: 36px;
            border-radius: 50%;
            border: none;
            font-size: 18px;
            font-weight: bold;
            cursor: pointer;
            display: flex;
            align-items: center;
            justify-content: center;
            transition: all 0.3s ease;
            margin-left: 5px;
        }
        
        #addPartBtn {
            background: #48bb78;
            color: white;
        }
        
        #addPartBtn:hover {
            background: #38a169;
            transform: scale(1.1);
        }
        
        #removePartBtn {
            background: #f56565;
            color: white;
        }
        
        #removePartBtn:hover {
            background: #e53e3e;
            transform: scale(1.1);
        }
        
        #removePartBtn:disabled {
            background: #cbd5e0;
            cursor: not-allowed;
            transform: none;
        }
        
        .part-config-panel {
            background: white;
            border-radius: 0 15px 15px 15px;
            padding: 20px;
            border: 2px solid #cbd5e0;
            border-top: none;
            margin-bottom: 20px;
        }
        
        .config-row {
            display: flex;
            align-items: flex-start;
            gap: 15px;
            margin-bottom: 15px;
            flex-wrap: wrap;
        }
        
        .config-row label {
            width: 140px;
            font-weight: 600;
            color: #4a5568;
            padding-top: 10px;
        }
        
        .config-row input {
            flex: 1;
            min-width: 200px;
            padding: 10px 12px;
            border: 2px solid #e2e8f0;
            border-radius: 8px;
            font-size: 0.95rem;
            transition: all 0.3s ease;
        }
        
        .config-row input:focus {
            border-color: #5e72e4;
            box-shadow: 0 0 0 3px rgba(94, 114, 228, 0.1);
            outline: none;
        }
        
        .config-row textarea {
            flex: 1;
            min-width: 200px;
            padding: 10px 12px;
            border: 2px solid #e2e8f0;
            border-radius: 8px;
            font-size: 0.95rem;
            transition: all 0.3s ease;
            resize: vertical;
            min-height: 80px;
            font-family: inherit;
        }
        
        .config-row textarea:focus {
            border-color: #5e72e4;
            box-shadow: 0 0 0 3px rgba(94, 114, 228, 0.1);
            outline: none;
        }
        
        .selected-questions {
            display: flex;
            flex-wrap: wrap;
            gap: 8px;
            margin-top: 10px;
            flex: 1;
            min-width: 300px;
        }
        
        .question-tag {
            background: #5e72e4;
            color: white;
            padding: 5px 12px;
            border-radius: 20px;
            font-size: 0.85rem;
            font-weight: 600;
            display: flex;
            align-items: center;
            gap: 5px;
        }
        
        .question-tag .remove {
            cursor: pointer;
            font-weight: bold;
            opacity: 0.8;
            transition: opacity 0.2s;
        }
        
        .question-tag .remove:hover {
            opacity: 1;
        }
        
        .excluded-rows {
            display: flex;
            flex-wrap: wrap;
            gap: 8px;
            margin-top: 10px;
            flex: 1;
            min-width: 300px;
        }
        
        .row-tag {
            background: #e2e8f0;
            color: #4a5568;
            padding: 5px 12px;
            border-radius: 20px;
            font-size: 0.85rem;
            font-weight: 600;
            display: flex;
            align-items: center;
            gap: 5px;
            max-width: 250px;
        }
        
        .row-tag .content {
            flex: 1;
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
        }
        
        .row-tag .remove {
            cursor: pointer;
            font-weight: bold;
            opacity: 0.8;
            transition: opacity 0.2s;
            flex-shrink: 0;
        }
        
        .row-tag .remove:hover {
            opacity: 1;
        }
        
        .data-preview {
            background: white;
            border-radius: 15px;
            padding: 20px;
            margin-bottom: 30px;
            box-shadow: 0 4px 15px rgba(0, 0, 0, 0.05);
        }
        
        .data-preview h3 {
            color: #2d3748;
            margin-bottom: 15px;
        }
        
        .preview-controls {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 15px;
            flex-wrap: wrap;
            gap: 10px;
        }
        
        .legend {
            display: flex;
            gap: 20px;
            flex-wrap: wrap;
        }
        
        .legend-item {
            display: flex;
            align-items: center;
            gap: 8px;
            font-size: 0.9rem;
            color: #4a5568;
            padding: 5px 10px;
            border-radius: 6px;
            transition: all 0.2s ease;
        }
        
        .legend-item.clickable {
            cursor: pointer;
        }
        
        .legend-item.clickable:hover {
            background: #edf2f7;
            transform: translateY(-1px);
        }
        
        .legend-item.active {
            background: #e2e8f0;
            font-weight: 600;
            box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
        }
        
        .legend-color {
            width: 20px;
            height: 20px;
            border-radius: 4px;
            border: 1px solid #cbd5e0;
        }
        
        .shift-hint {
            background: #edf2f7;
            padding: 10px;
            border-radius: 8px;
            margin-bottom: 10px;
            font-size: 0.85rem;
            color: #4a5568;
            display: flex;
            align-items: center;
            gap: 8px;
        }
        
        .table-container {
            height: 400px;
            overflow: auto;
            border: 1px solid #e2e8f0;
            border-radius: 10px;
            position: relative;
        }
        
        .preview-table {
            width: 100%;
            border-collapse: collapse;
            font-size: 0.9rem;
            position: relative;
            user-select: none;
        }
        
        .preview-table thead {
            position: sticky;
            top: 0;
            z-index: 10;
            background: white;
        }
        
        .preview-table th {
            background: #f7fafc;
            padding: 10px;
            text-align: center;
            border: 1px solid #e2e8f0;
            font-weight: 600;
            color: #4a5568;
            position: relative;
            cursor: pointer;
            transition: all 0.3s ease;
            white-space: nowrap;
            min-width: 80px;
        }
        
        .preview-table th:hover {
            background: #edf2f7;
        }
        
        .preview-table th.selectable {
            background: #edf2f7;
        }
        
        .preview-table th.selected {
            color: white;
            font-weight: bold;
        }
        
        .preview-table th.part-1 {
            background: #fed7d7 !important;
            color: #742a2a;
        }
        
        .preview-table th.part-2 {
            background: #feebc8 !important;
            color: #7c2d12;
        }
        
        .preview-table th.part-3 {
            background: #c6f6d5 !important;
            color: #22543d;
        }
        
        .preview-table th.part-4 {
            background: #bee3f8 !important;
            color: #2c5282;
        }
        
        .preview-table td {
            padding: 8px;
            text-align: center;
            border: 1px solid #e2e8f0;
            white-space: nowrap;
        }
        
        .preview-table tr:nth-child(even) {
            background: #f8f9fe;
        }
        
        .preview-table tr:hover {
            background: #edf2f7;
        }
        
        .action-buttons {
            display: flex;
            justify-content: center;
            gap: 20px;
            margin: 30px 0;
        }
        
        .btn {
            padding: 14px 40px;
            border: none;
            border-radius: 50px;
            font-size: 1.1rem;
            font-weight: 600;
            cursor: pointer;
            transition: all 0.3s ease;
            box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
        }
        
        .btn-primary {
            background: linear-gradient(135deg, #5e72e4 0%, #825ee4 100%);
            color: white;
        }
        
        .btn-primary:hover {
            transform: translateY(-3px);
            box-shadow: 0 7px 20px rgba(94, 114, 228, 0.4);
        }
        
        .btn-secondary {
            background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
            color: white;
        }
        
        .btn-secondary:hover {
            transform: translateY(-3px);
            box-shadow: 0 7px 20px rgba(245, 87, 108, 0.4);
        }
        
        .btn:disabled {
            opacity: 0.6;
            cursor: not-allowed;
            transform: none;
        }
        
        .status-section {
            background: #f8f9fe;
            border-radius: 15px;
            padding: 20px;
            margin-bottom: 30px;
            max-height: 300px;
            overflow-y: auto;
        }
        
        .status-section h2 {
            color: #2d3748;
            margin-bottom: 15px;
            padding-bottom: 10px;
            border-bottom: 2px solid #e2e8f0;
        }
        
        .status-log {
            font-family: 'Courier New', monospace;
            background: #1a202c;
            color: #e2e8f0;
            padding: 15px;
            border-radius: 10px;
            font-size: 0.9rem;
            line-height: 1.6;
            white-space: pre-wrap;
            max-height: 200px;
            overflow-y: auto;
        }
        
        .results-section {
            margin-top: 30px;
        }
        
        .results-section h2 {
            color: #2d3748;
            margin-bottom: 20px;
            padding-bottom: 10px;
            border-bottom: 2px solid #e2e8f0;
        }
        
        .result-card {
            background: white;
            border-radius: 15px;
            padding: 25px;
            margin-bottom: 25px;
            box-shadow: 0 4px 15px rgba(0, 0, 0, 0.05);
            border: 1px solid #e2e8f0;
        }
        
        .result-card h3 {
            color: #2d3748;
            margin-bottom: 15px;
            display: flex;
            align-items: center;
            gap: 10px;
        }
        
        .result-card h3::before {
            content: "📊";
            font-size: 1.5rem;
        }
        
        .data-table {
            width: 100%;
            border-collapse: collapse;
            margin-top: 15px;
        }
        
        .data-table th {
            background: linear-gradient(135deg, #5e72e4 0%, #825ee4 100%);
            color: white;
            padding: 12px 15px;
            text-align: left;
            font-weight: 600;
        }
        
        .data-table td {
            padding: 12px 15px;
            border-bottom: 1px solid #e2e8f0;
        }
        
        .data-table tr:nth-child(even) {
            background: #f8f9fe;
        }
        
        .data-table tr:hover {
            background: #edf2f7;
        }
        
        .download-btn {
            display: inline-block;
            background: linear-gradient(135deg, #11cdef 0%, #1171ef 100%);
            color: white;
            padding: 10px 25px;
            border-radius: 50px;
            text-decoration: none;
            font-weight: 600;
            margin-top: 15px;
            transition: all 0.3s ease;
            box-shadow: 0 4px 15px rgba(17, 205, 239, 0.3);
        }
        
        .download-btn:hover {
            transform: translateY(-2px);
            box-shadow: 0 6px 20px rgba(17, 205, 239, 0.4);
        }
        
        .hidden {
            display: none;
        }
        
        footer {
            background: #2d3748;
            color: white;
            text-align: center;
            padding: 20px;
            margin-top: 30px;
        }
        
        .loading {
            display: inline-block;
            width: 20px;
            height: 20px;
            border: 3px solid rgba(255, 255, 255, 0.3);
            border-radius: 50%;
            border-top-color: white;
            animation: spin 1s ease-in-out infinite;
            margin-right: 10px;
        }
        
        /* 比较分析相关样式 */
        .compare-analysis-results {
            margin-top: 15px;
        }
        
        .analysis-section {
            margin-bottom: 25px;
            padding: 15px;
            background-color: #f8f9fa;
            border-radius: 8px;
            border: 1px solid #e9ecef;
        }
        
        .analysis-section h4 {
            margin-top: 0;
            color: #2d3748;
            border-bottom: 1px solid #dee2e6;
            padding-bottom: 8px;
            margin-bottom: 15px;
        }
        
        .success-message {
            color: #28a745;
            font-weight: 500;
            padding: 10px;
            background-color: #d4edda;
            border: 1px solid #c3e6cb;
            border-radius: 4px;
            margin: 0;
        }
        
        .error-message {
            color: #dc3545;
            font-weight: 500;
            padding: 10px;
            background-color: #f8d7da;
            border: 1px solid #f5c6cb;
            border-radius: 4px;
            margin: 0;
        }
        
        .help-text {
            color: #6c757d;
            font-style: italic;
            margin: 0;
            padding: 10px;
            background-color: #e9ecef;
            border-radius: 4px;
        }
        
        /* 调整通用loading样式，适用于比较分析中的灰色背景 */
        .compare-analysis-results .loading {
            width: 16px;
            height: 16px;
            border-color: rgba(0, 0, 0, 0.1);
            border-top-color: #007bff;
        }
        
        @keyframes spin {
            to { transform: rotate(360deg); }
        }
        
        .alert {
            padding: 15px 20px;
            border-radius: 10px;
            margin: 20px 0;
            display: flex;
            align-items: center;
            gap: 10px;
            animation: slideIn 0.3s ease;
        }
        
        @keyframes slideIn {
            from {
                transform: translateY(-20px);
                opacity: 0;
            }
            to {
                transform: translateY(0);
                opacity: 1;
            }
        }
        
        .alert-error {
            background: #fed7d7;
            color: #742a2a;
            border: 1px solid #fc8181;
        }
        
        .alert-success {
            background: #c6f6d5;
            color: #22543d;
            border: 1px solid #68d391;
        }
        
        .alert-info {
            background: #bee3f8;
            color: #2c5282;
            border: 1px solid #63b3ed;
        }
        
        .help-text {
            font-size: 0.85rem;
            color: #718096;
            margin-top: 5px;
        }
        
        @media (max-width: 768px) {
            header h1 {
                font-size: 2rem;
            }
            
            .header-row-setting {
                position: static;
                margin-top: 15px;
                justify-content: center;
            }
            
            .step-indicator {
                flex-direction: column;
                align-items: center;
            }
            
            .part-selector {
                flex-direction: column;
            }
            
            .action-buttons {
                flex-direction: column;
                align-items: center;
            }
            
            .btn {
                width: 100%;
                max-width: 300px;
            }
        }
    </style>
</head>
<body>
    <div class="container">
        <header>
            <h1>交互式成绩分析工具</h1>
            <div class="header-row-setting">
                <label for="headerRow">题号行:</label>
                <input type="number" id="headerRow" value="2" min="1" onchange="updatePreview()">
            </div>
        </header>
        
        <main>
            <div class="step-indicator">
                <div class="step active" id="step1">
                    <div class="step-number">1</div>
                    <span>上传文件</span>
                </div>
                <div class="step" id="step2">
                    <div class="step-number">2</div>
                    <span>配置分析部分</span>
                </div>
                <div class="step" id="step3">
                    <div class="step-number">3</div>
                    <span>查看结果</span>
                </div>
            </div>
            
            <section class="file-upload">
                <input type="file" id="fileInput" accept=".xlsx,.csv">
                <label for="fileInput">📁 选择成绩文件</label>
                <div class="file-name" id="fileName">未选择文件</div>
            </section>
            
            <section class="config-section hidden" id="configSection">
                <div class="part-selector">
                    <div class="part-tab active" data-part="1" onclick="switchPart(1)">第1部分</div>
                    <div class="part-tab" data-part="2" onclick="switchPart(2)">第2部分</div>
                    <div class="part-tab" data-part="3" onclick="switchPart(3)">第3部分</div>
                    <div class="part-tab hidden" data-part="4" onclick="switchPart(4)">第4部分</div>
                    <div class="part-tab hidden" data-part="5" onclick="switchPart(5)">第5部分</div>
                    <div class="part-tab hidden" data-part="6" onclick="switchPart(6)">第6部分</div>
                    <div class="part-tab hidden" data-part="7" onclick="switchPart(7)">第7部分</div>
                    <div class="part-tab hidden" data-part="8" onclick="switchPart(8)">第8部分</div>
                    <button class="part-control-btn" id="addPartBtn" onclick="addPart()">+</button>
                    <button class="part-control-btn" id="removePartBtn" onclick="removePart()">-</button>
                </div>
                
                <div class="part-config-panel" id="partConfigPanel">
                    <div class="config-row">
                        <label>已选列:</label>
                        <div id="selectedQuestions" class="selected-questions">
                            <span class="help-text">请在下方表格中点击或按住Shift键点击多列进行选择</span>
                        </div>
                    </div>
                    <div class="config-row">
                        <label>评分阈值:</label>
                        <input type="text" id="thresholdInput" placeholder="优秀最低分,良好最低分,合格最低分 (支持中英文逗号，例如: 38,34,26 或 38，34，26)">
                    </div>
                    <div class="config-row">
                        <label>快速设置:</label>
                        <button class="btn btn-secondary" style="padding: 8px 20px; font-size: 0.9rem;" onclick="setThresholds(40, 35, 25)">40,35,25</button>
                        <button class="btn btn-secondary" style="padding: 8px 20px; font-size: 0.9rem;" onclick="setThresholds(38, 34, 26)">38,34,26</button>
                        <button class="btn btn-secondary" style="padding: 8px 20px; font-size: 0.9rem;" onclick="setThresholds(36, 32, 24)">36,32,24</button>
                    </div>
                </div>
                
                <div class="config-row" style="margin-top: 20px;">
                    <label>不参与计算的行:</label>
                    <textarea id="excludedRowsInput" placeholder="每行输入一个标识内容，如：班级均分、年级均分、汇总等" onchange="updateExcludedRows()"></textarea>
                    <div class="help-text">(系统自动识别，一般无需操作)</div>
                </div>
                <div class="config-row">
                    <label></label>
                    <div id="excludedRowsList" class="excluded-rows">
                        <span class="help-text">自动检测非数字行，显示第一列内容</span>
                    </div>
                </div>
            </section>
            
            <section class="data-preview hidden" id="dataPreview">
                <h3>数据预览 - Shift键多选列</h3>
                <div class="preview-controls">
                    <div class="legend">
                        <div class="legend-item clickable" data-part="1" onclick="switchPart(1)">
                            <div class="legend-color" style="background: #fed7d7;"></div>
                            <span>第1部分</span>
                        </div>
                        <div class="legend-item clickable" data-part="2" onclick="switchPart(2)">
                            <div class="legend-color" style="background: #feebc8;"></div>
                            <span>第2部分</span>
                        </div>
                        <div class="legend-item clickable" data-part="3" onclick="switchPart(3)">
                            <div class="legend-color" style="background: #c6f6d5;"></div>
                            <span>第3部分</span>
                        </div>
                        <div class="legend-item clickable hidden" id="legend-part-4" data-part="4" onclick="switchPart(4)">
                            <div class="legend-color" style="background: #bee3f8;"></div>
                            <span>第4部分</span>
                        </div>
                        <div class="legend-item clickable hidden" id="legend-part-5" data-part="5" onclick="switchPart(5)">
                            <div class="legend-color" style="background: #e9d8fd;"></div>
                            <span>第5部分</span>
                        </div>
                        <div class="legend-item clickable hidden" id="legend-part-6" data-part="6" onclick="switchPart(6)">
                            <div class="legend-color" style="background: #fed7cc;"></div>
                            <span>第6部分</span>
                        </div>
                        <div class="legend-item clickable hidden" id="legend-part-7" data-part="7" onclick="switchPart(7)">
                            <div class="legend-color" style="background: #c6f6d5;"></div>
                            <span>第7部分</span>
                        </div>
                        <div class="legend-item clickable hidden" id="legend-part-8" data-part="8" onclick="switchPart(8)">
                            <div class="legend-color" style="background: #bee3f8;"></div>
                            <span>第8部分</span>
                        </div>
                    </div>
                </div>
                <div class="shift-hint">
                    ⌨️ 按住Shift键点击可选择多列 | 单击选择/取消单列
                </div>
                <div class="table-container">
                    <div id="previewTableContainer"></div>
                </div>
            </section>
            
            <div class="action-buttons hidden" id="actionButtons">
                <button class="btn btn-primary" id="analyzeBtn">
                    <span id="btnText">开始分析</span>
                </button>
                <button class="btn btn-secondary" id="resetBtn">重置设置</button>
            </div>
            
            <section class="status-section hidden" id="statusSection">
                <h2>处理状态</h2>
                <div class="status-log" id="statusLog"></div>
            </section>
            
            <section class="results-section hidden" id="resultsSection">
                <h2>分析结果</h2>
                
                <div class="result-card">
                    <h3>成绩统计摘要</h3>
                    <div id="summaryTable"></div>
                    <a href="#" class="download-btn hidden" id="downloadSummary" download="summary.csv">下载摘要报告</a>
                </div>
                
                <div class="result-card">
                    <h3>学生成绩详情</h3>
                    <div id="detailsTable"></div>
                    <a href="#" class="download-btn hidden" id="downloadDetails" download="details.csv">下载详情报告</a>
                </div>
                
                <div class="result-card">
                    <div style="display: flex; justify-content: space-between; align-items: center;">
                        <h3>比较分析</h3>
                        <button class="btn btn-primary hidden" style="padding: 8px 20px; font-size: 0.9rem;" id="compareAnalysisBtn">执行比较分析</button>
                    </div>
                    <div id="compareAnalysisResults" style="margin-top: 20px;">
                        <p class="help-text">点击上方按钮执行比较分析，查看班级与年级均分对比以及最低得分率题目</p>
                    </div>
                    <a href="#" class="download-btn hidden" id="downloadCompareAnalysis" download="compare_analysis.csv">下载比较分析报告</a>
                </div>
            </section>
        </main>
        
        <footer>
            <p>© 2025 交互式成绩分析工具 | lkxbird@qq.com</p>
        </footer>
    </div>

    <script>
        // 全局变量
        let fileData = null;
        let fileName = '';
        let headerRow = 2;
        let currentPart = 1;
        let lastSelectedColumn = -1;
        let isShiftPressed = false;
        let excludedRows = [];
        let excludedRowContents = [];
        
        let partsConfig = {
            1: {name: '第1部分', columns: [], thresholds: []},
            2: {name: '第2部分', columns: [], thresholds: []},
            3: {name: '第3部分', columns: [], thresholds: []},
            4: {name: '第4部分', columns: [], thresholds: []},
            5: {name: '第5部分', columns: [], thresholds: []},
            6: {name: '第6部分', columns: [], thresholds: []},
            7: {name: '第7部分', columns: [], thresholds: []},
            8: {name: '第8部分', columns: [], thresholds: []}
        };
        
        // DOM元素
        const fileInput = document.getElementById('fileInput');
        const fileNameEl = document.getElementById('fileName');
        const headerRowInput = document.getElementById('headerRow');
        const configSection = document.getElementById('configSection');
        const dataPreview = document.getElementById('dataPreview');
        const actionButtons = document.getElementById('actionButtons');
        const analyzeBtn = document.getElementById('analyzeBtn');
        const resetBtn = document.getElementById('resetBtn');
        const btnText = document.getElementById('btnText');
        const statusSection = document.getElementById('statusSection');
        const statusLog = document.getElementById('statusLog');
        const resultsSection = document.getElementById('resultsSection');
        const summaryTable = document.getElementById('summaryTable');
        const detailsTable = document.getElementById('detailsTable');
        const downloadSummary = document.getElementById('downloadSummary');
        const downloadDetails = document.getElementById('downloadDetails');
        const selectedQuestions = document.getElementById('selectedQuestions');
        const thresholdInput = document.getElementById('thresholdInput');
        const excludedRowsInput = document.getElementById('excludedRowsInput');
        const excludedRowsList = document.getElementById('excludedRowsList');
        const compareAnalysisBtn = document.getElementById('compareAnalysisBtn');
        const compareAnalysisResults = document.getElementById('compareAnalysisResults');
        const downloadCompareAnalysis = document.getElementById('downloadCompareAnalysis');
        
        // 事件监听器
        fileInput.addEventListener('change', handleFileSelect);
        analyzeBtn.addEventListener('click', runAnalysis);
        resetBtn.addEventListener('click', resetSettings);
        compareAnalysisBtn.addEventListener('click', runCompareAnalysis);
        
        // 初始化部分按钮状态
        initializePartButtons();
        
        // 监听键盘事件
        document.addEventListener('keydown', (e) => {
            if (e.key === 'Shift') isShiftPressed = true;
        });
        
        document.addEventListener('keyup', (e) => {
            if (e.key === 'Shift') isShiftPressed = false;
        });
        
        // 处理文件选择
        function handleFileSelect(e) {
            const file = e.target.files[0];
            if (!file) return;
            
            fileName = file.name;
            fileNameEl.textContent = fileName;
            
            const reader = new FileReader();
            reader.onload = function(e) {
                const data = e.target.result;
                if (fileName.endsWith('.xlsx')) {
                    const workbook = XLSX.read(data, {type: 'binary'});
                    const firstSheet = workbook.Sheets[workbook.SheetNames[0]];
                    fileData = XLSX.utils.sheet_to_json(firstSheet, {header: 1});
                } else if (fileName.endsWith('.csv')) {
                    fileData = parseCSV(data);
                }
                
                // 自动检测排除行
                detectExcludedRows();
                
                // 显示后续步骤
                configSection.classList.remove('hidden');
                dataPreview.classList.remove('hidden');
                actionButtons.classList.remove('hidden');
                
                // 更新步骤指示器
                document.getElementById('step1').classList.add('completed');
                document.getElementById('step1').classList.remove('active');
                document.getElementById('step2').classList.add('active');
                
                updatePreview();
                logStatus(`成功加载文件: ${fileName}`, 'info');
            };
            
            if (fileName.endsWith('.xlsx')) {
                reader.readAsBinaryString(file);
            } else {
                reader.readAsText(file, 'UTF-8');
            }
        }
        
        // 解析CSV
        function parseCSV(csvText) {
            const lines = csvText.split('\n');
            const result = [];
            
            for (let line of lines) {
                if (line.trim() === '') continue;
                
                const values = [];
                let currentValue = '';
                let inQuotes = false;
                
                for (let i = 0; i < line.length; i++) {
                    const char = line[i];
                    
                    if (char === '"') {
                        inQuotes = !inQuotes;
                    } else if (char === ',' && !inQuotes) {
                        values.push(currentValue.trim());
                        currentValue = '';
                    } else {
                        currentValue += char;
                    }
                }
                
                values.push(currentValue.trim());
                result.push(values);
            }
            
            return result;
        }
        
        // 自动检测排除行
        function detectExcludedRows() {
            excludedRows = [];
            excludedRowContents = [];
            
            for (let i = 0; i < fileData.length; i++) {
                const row = fileData[i];
                if (row.length > 0) {
                    const firstCell = String(row[0]).trim();
                    // 检查第一列是否不是数字 - 这是唯一的排除条件
                    if (!/^\d+$/.test(firstCell) && firstCell !== '') {
                        excludedRows.push(i + 1); // 转换为1-based索引
                        excludedRowContents.push(firstCell);
                    }
                }
            }
            
            // 更新输入框和显示
            excludedRowsInput.value = excludedRowContents.join('\n');
            updateExcludedRowsDisplay();
            
            logStatus(`自动检测到 ${excludedRows.length} 行不参与计算: ${excludedRowContents.join(', ')}`, 'info');
        }
        
        // 更新排除行
        function updateExcludedRows() {
            const input = excludedRowsInput.value.trim();
            if (input) {
                const contents = input.split('\n').map(c => c.trim()).filter(c => c !== '');
                excludedRowContents = contents;
                
                // 根据内容查找对应的行号
                excludedRows = [];
                for (let i = 0; i < fileData.length; i++) {
                    const firstCell = String(fileData[i][0]).trim();
                    if (contents.includes(firstCell)) {
                        excludedRows.push(i + 1);
                    }
                }
            } else {
                // 如果用户清空输入，则真正清空排除行
                excludedRows = [];
                excludedRowContents = [];
            }
            updateExcludedRowsDisplay();
        }
        
        // 更新排除行显示
        function updateExcludedRowsDisplay() {
            if (excludedRowContents.length === 0) {
                excludedRowsList.innerHTML = '<span class="help-text">暂无排除行</span>';
                excludedRowsInput.value = '';
            } else {
                let html = '';
                excludedRowContents.forEach((content, index) => {
                    const rowNum = excludedRows[index];
                    html += `<span class="row-tag" title="第${rowNum}行"><span class="content">${content}</span><span class="remove" onclick="removeExcludedRow(${index})">×</span></span>`;
                });
                excludedRowsList.innerHTML = html;
                // 更新输入框
                excludedRowsInput.value = excludedRowContents.join('\n');
            }
        }
        
        // 移除排除行
        function removeExcludedRow(index) {
            excludedRows.splice(index, 1);
            excludedRowContents.splice(index, 1);
            excludedRowsInput.value = excludedRowContents.join('\n');
            updateExcludedRowsDisplay();
        }
        
        // 添加部分
        function addPart() {
            // 查找当前可见的部分数量
            let visibleParts = 0;
            for (let i = 1; i <= 8; i++) {
                const tab = document.querySelector(`.part-tab[data-part="${i}"]`);
                if (tab && !tab.classList.contains('hidden')) {
                    visibleParts++;
                }
            }
            
            // 如果已达到最大部分数，则返回
            if (visibleParts >= 8) {
                showAlert('最多只能添加8个部分', 'error');
                return;
            }
            
            // 显示下一个隐藏的部分
            for (let i = 1; i <= 8; i++) {
                const tab = document.querySelector(`.part-tab[data-part="${i}"]`);
                if (tab && tab.classList.contains('hidden')) {
                    tab.classList.remove('hidden');
                    
                    // 显示对应的图例
                    const legend = document.getElementById(`legend-part-${i}`);
                    if (legend) {
                        legend.classList.remove('hidden');
                    }
                    
                    // 如果这是第一个显示的部分，设置为活动状态
                    if (visibleParts === 0) {
                        switchPart(i);
                    }
                    
                    // 更新按钮状态
                    updatePartButtons();
                    break;
                }
            }
        }
        
        // 删除部分
        function removePart() {
            // 查找当前可见的部分数量
            let visibleParts = [];
            for (let i = 1; i <= 8; i++) {
                const tab = document.querySelector(`.part-tab[data-part="${i}"]`);
                if (tab && !tab.classList.contains('hidden')) {
                    visibleParts.push(i);
                }
            }
            
            // 如果只剩1个部分，则不能删除
            if (visibleParts.length <= 1) {
                showAlert('至少需要保留1个部分', 'error');
                return;
            }
            
            // 隐藏最后一个可见的部分
            const lastPart = visibleParts[visibleParts.length - 1];
            const tab = document.querySelector(`.part-tab[data-part="${lastPart}"]`);
            if (tab) {
                tab.classList.add('hidden');
                
                // 隐藏对应的图例
                const legend = document.getElementById(`legend-part-${lastPart}`);
                if (legend) {
                    legend.classList.add('hidden');
                }
                
                // 如果删除的是当前活动部分，则切换到前一个部分
                if (currentPart === lastPart) {
                    const prevPart = visibleParts[visibleParts.length - 2];
                    switchPart(prevPart);
                }
                
                // 清空该部分的配置
                partsConfig[lastPart].columns = [];
                partsConfig[lastPart].thresholds = [];
                
                // 更新按钮状态
                updatePartButtons();
            }
        }
        
        // 更新部分按钮状态
        function updatePartButtons() {
            // 查找当前可见的部分数量
            let visibleParts = 0;
            for (let i = 1; i <= 8; i++) {
                const tab = document.querySelector(`.part-tab[data-part="${i}"]`);
                if (tab && !tab.classList.contains('hidden')) {
                    visibleParts++;
                }
            }
            
            // 更新添加按钮状态
            const addBtn = document.getElementById('addPartBtn');
            if (visibleParts >= 8) {
                addBtn.disabled = true;
            } else {
                addBtn.disabled = false;
            }
            
            // 更新删除按钮状态
            const removeBtn = document.getElementById('removePartBtn');
            if (visibleParts <= 1) {
                removeBtn.disabled = true;
            } else {
                removeBtn.disabled = false;
            }
        }
        
        // 初始化部分按钮状态
        function initializePartButtons() {
            updatePartButtons();
            
            // 确保第一个图例项处于活动状态
            document.querySelectorAll('.legend-item').forEach(item => {
                item.classList.remove('active');
            });
            const firstLegendItem = document.querySelector('.legend-item[data-part="1"]');
            if (firstLegendItem) {
                firstLegendItem.classList.add('active');
            }
        }
        function updatePreview() {
            headerRow = parseInt(headerRowInput.value);
            if (isNaN(headerRow) || headerRow < 1) {
                showAlert('题号所在行号无效', 'error');
                return;
            }
            
            if (!fileData || fileData.length < headerRow) {
                showAlert('文件数据不足', 'error');
                return;
            }
            
            // 获取表头和所有数据
            const header = fileData[headerRow - 1];
            const allData = fileData.slice(headerRow);
            
            let html = '<table class="preview-table"><thead><tr>';
            
            // 表头
            for (let i = 0; i < header.length; i++) {
                const colName = String(header[i]).trim();
                const partNum = getPartForColumn(i);
                
                let className = 'selectable';
                if (partNum) {
                    className += ` part-${partNum} selected`;
                }
                
                html += `<th class="${className}" onclick="handleColumnClick(${i})" title="点击选择，按住Shift键点击多选">${colName}</th>`;
            }
            
            html += '</tr></thead><tbody>';
            
            // 数据行
            for (let rowIdx = 0; rowIdx < allData.length; rowIdx++) {
                const actualRowNum = headerRow + rowIdx;
                const isExcluded = excludedRows.includes(actualRowNum);
                
                html += `<tr ${isExcluded ? 'class="excluded"' : ''}>`;
                for (let i = 0; i < allData[rowIdx].length && i < header.length; i++) {
                    html += `<td>${allData[rowIdx][i] || ''}</td>`;
                }
                html += '</tr>';
            }
            
            html += '</tbody></table>';
            document.getElementById('previewTableContainer').innerHTML = html;
        }
        
        // 处理列点击
        function handleColumnClick(colIndex) {
            if (isShiftPressed && lastSelectedColumn >= 0) {
                // Shift键：选择连续列
                const start = Math.min(lastSelectedColumn, colIndex);
                const end = Math.max(lastSelectedColumn, colIndex);
                
                // 清除当前部分的选择
                partsConfig[currentPart].columns = [];
                
                for (let i = start; i <= end; i++) {
                    removeFromAllParts(i);
                    partsConfig[currentPart].columns.push(i);
                }
            } else {
                // 普通点击：切换选择
                const currentPartNum = getPartForColumn(colIndex);
                
                if (currentPartNum === currentPart) {
                    // 从当前部分移除
                    removeFromAllParts(colIndex);
                } else if (currentPartNum) {
                    // 从其他部分移除，添加到当前部分
                    removeFromAllParts(colIndex);
                    partsConfig[currentPart].columns.push(colIndex);
                } else {
                    // 添加到当前部分
                    partsConfig[currentPart].columns.push(colIndex);
                }
                
                lastSelectedColumn = colIndex;
            }
            
            updatePreview();
            updateSelectedQuestions();
        }
        
        // 从所有部分移除列
        function removeFromAllParts(colIndex) {
            for (let part = 1; part <= 8; part++) {
                const index = partsConfig[part].columns.indexOf(colIndex);
                if (index > -1) {
                    partsConfig[part].columns.splice(index, 1);
                }
            }
        }
        
        // 获取列所属部分
        function getPartForColumn(colIndex) {
            for (let part = 1; part <= 8; part++) {
                if (partsConfig[part].columns.includes(colIndex)) {
                    return part;
                }
            }
            return null;
        }
        
        // 切换部分
        function switchPart(partNum) {
            // 检查部分是否可见
            const tab = document.querySelector(`.part-tab[data-part="${partNum}"]`);
            if (tab && tab.classList.contains('hidden')) {
                return;
            }
            
            // 切换前保存当前部分的配置
            saveCurrentPartConfig();
            
            currentPart = partNum;
            
            // 更新标签样式
            document.querySelectorAll('.part-tab').forEach(tab => {
                tab.classList.remove('active');
            });
            document.querySelector(`.part-tab[data-part="${partNum}"]`).classList.add('active');
            
            // 更新图例项样式
            document.querySelectorAll('.legend-item').forEach(item => {
                item.classList.remove('active');
            });
            document.querySelector(`.legend-item[data-part="${partNum}"]`).classList.add('active');
            
            // 更新阈值输入
            const thresholds = partsConfig[partNum].thresholds;
            if (thresholds.length > 0) {
                thresholdInput.value = thresholds.join(',');
            } else {
                thresholdInput.value = '';
            }
            
            updateSelectedQuestions();
        }
        
        // 更新已选列显示
        function updateSelectedQuestions() {
            const columns = partsConfig[currentPart].columns;
            const header = fileData[headerRow - 1];
            
            if (columns.length === 0) {
                selectedQuestions.innerHTML = '<span class="help-text">请在下方表格中点击或按住Shift键点击多列进行选择</span>';
            } else {
                let html = '';
                columns.forEach(colIndex => {
                    const colName = header[colIndex] || `列${colIndex + 1}`;
                    html += `<span class="question-tag">${colName}<span class="remove" onclick="removeColumn(${colIndex})">×</span></span>`;
                });
                selectedQuestions.innerHTML = html;
            }
        }
        
        // 移除列
        function removeColumn(colIndex) {
            const index = partsConfig[currentPart].columns.indexOf(colIndex);
            if (index > -1) {
                partsConfig[currentPart].columns.splice(index, 1);
            }
            updatePreview();
            updateSelectedQuestions();
        }
        
        // 设置阈值
        function setThresholds(excellent, good, pass) {
            thresholdInput.value = `${excellent},${good},${pass}`;
            partsConfig[currentPart].thresholds = [excellent, good, pass];
        }
        
        // 保存当前部分配置
        function saveCurrentPartConfig() {
            const thresholdStr = thresholdInput.value.trim();
            
            // 如果阈值输入框为空，清空阈值配置
            if (!thresholdStr) {
                partsConfig[currentPart].thresholds = [];
                return;
            }
            
            // 支持中文逗号和英文逗号作为分隔符
            const thresholds = thresholdStr.split(/[,，]/).map(t => parseFloat(t.trim()));
            if (thresholds.length === 3 && thresholds.every(t => !isNaN(t))) {
                partsConfig[currentPart].thresholds = thresholds;
            } else {
                // 如果阈值格式不正确，也清空阈值配置
                partsConfig[currentPart].thresholds = [];
            }
        }
        
        // 根据分数获取等级
        function getPerformanceLevel(score, thresholds) {
            const [excellentMin, goodMin, passMin] = thresholds;
            
            try {
                // 检查是否为有效数字
                if (typeof score === 'string' && (score.trim() === '' || score.trim() === '-')) {
                    return "无法评级"; // 空值或'-'直接返回无法评级
                }
                
                score = parseFloat(score);
                // 检查是否为有效数字
                if (isNaN(score)) {
                    return "无法评级";
                }
            } catch (e) {
                return "无法评级"; // 解析失败时返回无法评级
            }
            
            if (score >= excellentMin) return '优秀';
            if (score >= goodMin) return '良好';
            if (score >= passMin) return '合格';
            return '须努力';
        }
        
        // 运行分析
        function runAnalysis() {
            if (!fileData) {
                showAlert('请先选择成绩文件', 'error');
                return;
            }
            
            // 保存当前部分配置
            saveCurrentPartConfig();
            
            // 验证配置
            const validParts = [];
            for (let part = 1; part <= 8; part++) {
                // 检查部分是否可见
                const tab = document.querySelector(`.part-tab[data-part="${part}"]`);
                if (tab && !tab.classList.contains('hidden')) {
                    const config = partsConfig[part];
                    if (config.columns.length > 0 && config.thresholds.length === 3) {
                        validParts.push({
                            name: config.name,
                            questionColumns: config.columns,
                            thresholds: config.thresholds
                        });
                    }
                }
            }
            
            if (validParts.length === 0) {
                showAlert('请至少配置一个完整的分析部分（选择列并设置阈值）', 'error');
                return;
            }
            
            // 显示状态区域
            statusSection.classList.remove('hidden');
            resultsSection.classList.add('hidden');
            statusLog.innerHTML = '';
            
            // 禁用按钮并显示加载状态
            analyzeBtn.disabled = true;
            btnText.innerHTML = '<span class="loading"></span>分析中...';
            
            // 更新步骤指示器
            document.getElementById('step2').classList.add('completed');
            document.getElementById('step2').classList.remove('active');
            document.getElementById('step3').classList.add('active');
            
            // 使用setTimeout确保UI更新
            setTimeout(() => {
                try {
                    // 处理数据
                    const {summary, details} = processScores(validParts);
                    
                    // 更新排除行显示
                    updateExcludedRowsDisplay();
                    
                    // 显示结果
                    displayResults(summary, details);
                    
                    // 自动执行比较分析
                    performCompareAnalysis();
                    
                    logStatus('分析完成！已自动执行比较分析', 'success');
                    showAlert('成绩分析成功完成！已自动执行比较分析。', 'success');
                } catch (error) {
                    logStatus(`分析失败: ${error.message}`, 'error');
                    showAlert(`分析失败: ${error.message}`, 'error');
                } finally {
                    // 恢复按钮状态
                    analyzeBtn.disabled = false;
                    btnText.textContent = '开始分析';
                }
            }, 100);
        }
        
        // 处理分数数据
        function processScores(partsConfig) {
            logStatus(`开始处理文件: ${fileName}`, 'info');
            
            // 获取表头和数据
            const header = fileData[headerRow - 1];
            const allData = fileData.slice(headerRow);
            
            if (!header || allData.length === 0) {
                throw new Error('文件数据不足或表头行号设置错误');
            }
            
            // 过滤掉排除行 - 优先使用用户设置的排除行
            const data = [];
            for (let i = 0; i < allData.length; i++) {
                const actualRowNum = headerRow + i;
                const firstCell = String(allData[i][0]).trim();
                
                // 如果用户有手动设置排除行，则只排除用户指定的行
                if (excludedRowContents.length > 0) {
                    if (!excludedRowContents.includes(firstCell)) {
                        data.push(allData[i]);
                    }
                } else {
                    // 如果用户没有手动设置，则使用自动检测逻辑
                    if (/^\d+$/.test(firstCell) && firstCell !== '') {
                        data.push(allData[i]);
                    }
                }
            }
            
            // 计算实际排除的行数
            const excludedCount = allData.length - data.length;
            logStatus(`成功读取文件，表头行: ${headerRow}，总数据行数: ${allData.length}，排除行数: ${excludedCount}，有效数据行数: ${data.length}`, 'info');
            
            // 解析表头，建立映射
            logStatus('正在解析表头...', 'info');
            let studentNameColIdx = null;
            let studentIdColIdx = null;
            
            for (let i = 0; i < header.length; i++) {
                const colName = String(header[i]).trim();
                
                if (colName === '姓名') {
                    studentNameColIdx = i;
                    logStatus(`  找到学生姓名列 '姓名' 在列索引 ${i}`, 'info');
                } else if (colName === '班内学号') {
                    studentIdColIdx = i;
                    logStatus(`  找到学生学号列 '班内学号' 在列索引 ${i}`, 'info');
                }
            }
            
            if (!studentNameColIdx) {
                logStatus("警告：未找到学生姓名列 '姓名'。将使用 '未知(数据行号)' 作为姓名。", 'error');
            }
            if (!studentIdColIdx) {
                logStatus("警告：未找到学生学号列 '班内学号'。将使用 'N/A' 作为学号。", 'error');
            }
            
            // 初始化数据存储结构
            const levels = ['优秀', '良好', '合格', '须努力'];
            const summaryCounts = {};
            for (const part of partsConfig) {
                summaryCounts[part.name] = {};
                for (const level of levels) {
                    summaryCounts[part.name][level] = 0;
                }
            }
            
            const studentDetails = [];
            
            // 处理学生数据
            logStatus('开始处理学生数据...', 'info');
            for (let rowIdx = 0; rowIdx < data.length; rowIdx++) {
                const studentRow = data[rowIdx];
                const dataRowNumber = rowIdx + 1;
                
                // 跳过空行
                if (!studentRow || studentRow.every(cell => !cell || String(cell).trim() === '')) {
                    logStatus(`  信息：跳过空的数据行，行号（数据区）：${dataRowNumber}`, 'info');
                    continue;
                }
                
                // 获取学号和姓名
                let studentName = `未知(数据行${dataRowNumber})`;
                if (studentNameColIdx !== null && studentRow[studentNameColIdx] !== undefined) {
                    const nameVal = studentRow[studentNameColIdx];
                    if (nameVal !== null && nameVal !== undefined) {
                        const nameStr = String(nameVal).trim();
                        studentName = nameStr || `空姓名(数据行${dataRowNumber})`;
                    }
                }
                
                let studentId = 'N/A';
                if (studentIdColIdx !== null && studentRow[studentIdColIdx] !== undefined) {
                    const idVal = studentRow[studentIdColIdx];
                    if (idVal !== null && idVal !== undefined) {
                        const idStr = String(idVal).trim();
                        studentId = idStr || '空学号';
                    }
                }
                
                const studentRecord = {
                    '学号': studentId,
                    '姓名': studentName
                };
                
                // 计算每个部分的得分和等级
                for (const part of partsConfig) {
                    const {name, questionColumns, thresholds} = part;
                    
                    let sectionScore = 0;
                    let validScoreFound = false;
                    
                    for (const colIdx of questionColumns) {
                        if (colIdx < studentRow.length) {
                            const scoreVal = studentRow[colIdx];
                            if (scoreVal !== null && scoreVal !== undefined && String(scoreVal).trim() !== '') {
                                try {
                                    sectionScore += parseFloat(scoreVal);
                                    validScoreFound = true;
                                } catch (e) {
                                    // 忽略无效分数
                                }
                            }
                        }
                    }
                    
                    // 确定等级
                    let level = '无法评级';
                    if (validScoreFound) {
                        level = getPerformanceLevel(sectionScore, thresholds);
                        if (level.startsWith('错误')) {
                            logStatus(`警告：学生 '${studentName}' ${name} 评级时出错: ${level}`, 'error');
                            level = '评级错误';
                        }
                    }
                    
                    // 存储学生个人等第
                    studentRecord[name] = level;
                    
                    // 统计各等第人数
                    // 只统计有效的等级类别，排除'无法评级'和'评级错误'
                    if (levels.includes(level) && level !== '无法评级' && level !== '评级错误') {
                        summaryCounts[name][level]++;
                    }
                }
                
                // 将该学生的完整记录添加到列表中
                studentDetails.push(studentRecord);
            }
            
            logStatus(`处理完成。共处理 ${studentDetails.length} 个学生数据行。`, 'success');
            
            return {
                summary: summaryCounts,
                details: studentDetails
            };
        }
        
        // 显示结果
        function displayResults(summary, details) {
            // 显示摘要表格
            const summaryHtml = createSummaryTable(summary);
            summaryTable.innerHTML = summaryHtml;
            
            // 显示详情表格
            const detailsHtml = createDetailsTable(details);
            detailsTable.innerHTML = detailsHtml;
            
            // 设置下载链接
            const summaryData = createSummaryCSV(summary);
            const detailsData = createDetailsCSV(details);
            
            downloadSummary.href = 'data:text/csv;charset=utf-8,' + encodeURIComponent(summaryData);
            downloadSummary.classList.remove('hidden');
            
            downloadDetails.href = 'data:text/csv;charset=utf-8,' + encodeURIComponent(detailsData);
            downloadDetails.classList.remove('hidden');
            
            // 显示结果区域
            resultsSection.classList.remove('hidden');
        }
        
        // 创建摘要表格HTML
        function createSummaryTable(summary) {
            const parts = Object.keys(summary);
            const levels = ['优秀', '良好', '合格', '须努力'];
            
            let html = '<table class="data-table"><thead><tr><th>部分</th>';
            for (const level of levels) {
                html += `<th>${level}</th>`;
            }
            html += '</tr></thead><tbody>';
            
            for (const part of parts) {
                html += `<tr><td>${part}</td>`;
                for (const level of levels) {
                    html += `<td>${summary[part][level]}</td>`;
                }
                html += '</tr>';
            }
            
            html += '</tbody></table>';
            return html;
        }
        
        // 创建详情表格HTML
        function createDetailsTable(details) {
            if (details.length === 0) return '<p>没有学生数据</p>';
            
            const headers = Object.keys(details[0]);
            
            let html = '<table class="data-table"><thead><tr>';
            for (const header of headers) {
                html += `<th>${header}</th>`;
            }
            html += '</tr></thead><tbody>';
            
            for (const student of details) {
                html += '<tr>';
                for (const header of headers) {
                    html += `<td>${student[header] || ''}</td>`;
                }
                html += '</tr>';
            }
            
            html += '</tbody></table>';
            return html;
        }
        
        // 创建摘要CSV
        function createSummaryCSV(summary) {
            const parts = Object.keys(summary);
            const levels = ['优秀', '良好', '合格', '须努力'];
            
            let csv = '\ufeff部分,' + levels.join(',') + '\n';
            
            for (const part of parts) {
                csv += part + ',' + levels.map(level => summary[part][level]).join(',') + '\n';
            }
            
            return csv;
        }
        
        // 创建详情CSV
        function createDetailsCSV(details) {
            if (details.length === 0) return '';
            
            const headers = Object.keys(details[0]);
            let csv = '\ufeff' + headers.join(',') + '\n';
            
            for (const student of details) {
                csv += headers.map(header => student[header] || '').join(',') + '\n';
            }
            
            return csv;
        }
        
        // 执行比较分析（直接使用已解析的数据）
        function performCompareAnalysis() {
            try {
                logStatus('开始执行比较分析...', 'info');
                
                // 使用已经解析好的数据
                const header = fileData[headerRow - 1];
                const allData = fileData.slice(headerRow);
                
                // 过滤排除行（与主分析保持一致的逻辑）
                const data = [];
                let classScoreRateRow = null;
                let gradeScoreRateRow = null;
                
                for (let i = 0; i < allData.length; i++) {
                    const firstCell = String(allData[i][0]).trim();
                    
                    // 严格识别班级得分率%和年级得分率%行，只使用这两行数据
                    if (firstCell === '班级得分率%') {
                        classScoreRateRow = allData[i];
                    } else if (firstCell === '年级得分率%') {
                        gradeScoreRateRow = allData[i];
                    }
                    
                    // 如果用户有手动设置排除行，则只排除用户指定的行
                    if (excludedRowContents.length > 0) {
                        if (!excludedRowContents.includes(firstCell)) {
                            data.push(allData[i]);
                        }
                    } else {
                        // 如果用户没有手动设置，则使用自动检测逻辑
                        if (/^\d+$/.test(firstCell) && firstCell !== '') {
                            data.push(allData[i]);
                        }
                    }
                }
                
                // 获取题目相关数据，传入班级得分率和年级得分率行
                const questionData = analyzeQuestions(data, header, classScoreRateRow, gradeScoreRateRow);
                
                // 显示比较分析结果
                displayCompareAnalysisResults(questionData);
                
                // 生成并提供下载
                const compareAnalysisCSV = createCompareAnalysisCSV(questionData);
                downloadCompareAnalysis.href = 'data:text/csv;charset=utf-8,' + encodeURIComponent(compareAnalysisCSV);
                downloadCompareAnalysis.classList.remove('hidden');
                
                logStatus('比较分析完成', 'success');
                return true;
            } catch (error) {
                logStatus(`比较分析时出错: ${error.message}`, 'error');
                compareAnalysisResults.innerHTML = `<p class="error-message">比较分析出错: ${error.message}</p>`;
                return false;
            }
        }
        
        // 原比较分析函数（保留但隐藏）
        function runCompareAnalysis() {
            performCompareAnalysis();
        }
        
        // 分析题目数据
        function analyzeQuestions(data, header, classScoreRateRow, gradeScoreRateRow) {
            // 找到姓名和学号列
            let studentNameColIdx = null;
            let studentIdColIdx = null;
            const questionColumns = [];
            const questionNames = [];
            
            for (let i = 0; i < header.length; i++) {
                const colName = String(header[i]).trim();
                
                if (colName === '姓名') {
                    studentNameColIdx = i;
                } else if (colName === '班内学号') {
                    studentIdColIdx = i;
                } else if (colName && !colName.includes('总分') && !colName.includes('等级')) {
                    // 认为其他列是题目列
                    questionColumns.push(i);
                    questionNames.push(colName);
                }
            }
            
            // 计算各题目的平均分和得分率
            const questionStats = [];
            
            for (let qIdx = 0; qIdx < questionColumns.length; qIdx++) {
                const colIdx = questionColumns[qIdx];
                const qName = questionNames[qIdx];
                
                let totalScore = 0;
                let validCount = 0;
                let maxScore = 0;
                
                for (let rowIdx = 0; rowIdx < data.length; rowIdx++) {
                    const cellValue = data[rowIdx][colIdx];
                    
                    if (cellValue !== null && cellValue !== undefined && String(cellValue).trim() !== '') {
                        try {
                            const score = parseFloat(cellValue);
                            if (!isNaN(score)) {
                                totalScore += score;
                                validCount++;
                                maxScore = Math.max(maxScore, score);
                            }
                        } catch (e) {
                            // 忽略无效分数
                        }
                    }
                }
                
                // 计算平均分和得分率，确保数据有效性
                const avgScore = validCount > 0 ? totalScore / validCount : 0;
                
                // 严格从班级得分率%行获取数据，如果存在的话
                let scoreRate = 0;
                if (classScoreRateRow && colIdx < classScoreRateRow.length) {
                    try {
                        const rate = parseFloat(classScoreRateRow[colIdx]);
                        if (!isNaN(rate) && isFinite(rate)) {
                            scoreRate = rate;
                        }
                    } catch (e) {
                        // 数据无效，继续使用计算值
                    }
                }
                
                // 如果无法从行中获取，则计算得分率
                if (scoreRate === 0 && maxScore > 0 && !isNaN(avgScore) && isFinite(avgScore)) {
                    scoreRate = (avgScore / maxScore) * 100;
                }
                
                // 严格从年级得分率%行获取数据，如果存在的话
                let gradeScoreRate = 0;
                if (gradeScoreRateRow && colIdx < gradeScoreRateRow.length) {
                    try {
                        const rate = parseFloat(gradeScoreRateRow[colIdx]);
                        if (!isNaN(rate) && isFinite(rate)) {
                            gradeScoreRate = rate;
                        }
                    } catch (e) {
                        // 数据无效，不使用模拟数据，保持为0
                    }
                }
                
                // 比较班级得分率%是否低于年级得分率%，只在两者都是有效数字时进行比较
                const isBelowGrade = !isNaN(scoreRate) && !isNaN(gradeScoreRate) && 
                                    isFinite(scoreRate) && isFinite(gradeScoreRate) && 
                                    scoreRate < gradeScoreRate;
                
                questionStats.push({
                    questionName: qName,
                    columnIndex: colIdx,
                    avgScore: avgScore,
                    scoreRate: scoreRate,
                    gradeScoreRate: gradeScoreRate,
                    validCount: validCount,
                    isBelowGrade: isBelowGrade
                });
            }
            
            // 找出班级得分率%低于年级得分率%的题目
            const belowGradeQuestions = questionStats
                .filter(q => q.isBelowGrade && !isNaN(q.scoreRate) && !isNaN(q.gradeScoreRate))
                .sort((a, b) => (b.gradeScoreRate - b.scoreRate) - (a.gradeScoreRate - a.scoreRate)); // 按差距排序
            
            // 找出得分率最低的10道题
            const lowestScoreRateQuestions = [...questionStats]
                .sort((a, b) => a.scoreRate - b.scoreRate)
                .slice(0, 10);
            
            return {
                allQuestions: questionStats,
                belowGradeQuestions: belowGradeQuestions,
                lowestScoreRateQuestions: lowestScoreRateQuestions
            };
        }
        
        // 显示比较分析结果
        function displayCompareAnalysisResults(questionData) {
            let html = '<div class="compare-analysis-results">';
            
            // 添加数据源说明
            html += '<p class="data-source-note" style="font-size: 12px; color: #666; margin-bottom: 15px;">';
            html += '注：分析使用CSV文件中第46行（班级得分率%）和第48行（年级得分率%）的数据。';
            html += '</p>';
            
            // 显示班级得分率%低于年级得分率%的题目
            html += '<div class="analysis-section">';
            html += '<h4>一、班级得分率%低于年级得分率%的题目</h4>';
            
            if (questionData.belowGradeQuestions.length > 0) {
                html += '<table class="data-table">';
                html += '<thead><tr><th>题目名称</th><th>班级得分率(%)</th><th>年级得分率(%)</th><th>差距</th></tr></thead>';
                html += '<tbody>';
                
                for (const q of questionData.belowGradeQuestions) {
                    const difference = q.gradeScoreRate - q.scoreRate;
                    html += `<tr>
                        <td>${q.questionName}</td>
                        <td>${q.scoreRate.toFixed(2)}</td>
                        <td>${q.gradeScoreRate.toFixed(2)}</td>
                        <td>${difference.toFixed(2)}</td>
                    </tr>`;
                }
                
                html += '</tbody></table>';
            } else {
                html += '<p>没有发现班级得分率%低于年级得分率%的题目</p>';
            }
            
            html += '</div>';
            
            // 显示得分率最低的10道题
            html += '<div class="analysis-section" style="margin-top: 30px;">';
            html += '<h4>二、班级得分率最低的10道题</h4>';
            
            if (questionData.lowestScoreRateQuestions.length > 0) {
                html += '<table class="data-table">';
                html += '<thead><tr><th>排名</th><th>题目名称</th><th>得分率(%)</th></tr></thead>';
                html += '<tbody>';
                
                for (let i = 0; i < questionData.lowestScoreRateQuestions.length; i++) {
                    const q = questionData.lowestScoreRateQuestions[i];
                    html += `<tr>
                        <td>${i + 1}</td>
                        <td>${q.questionName}</td>
                        <td>${q.scoreRate.toFixed(2)}%</td>
                    </tr>`;
                }
                
                html += '</tbody></table>';
            } else {
                html += '<p>没有足够的题目数据进行分析</p>';
            }
            
            html += '</div>';
            
            html += '</div>';
            
            compareAnalysisResults.innerHTML = html;
        }
        
        // 创建比较分析CSV - 使用CSV文件中第46行（班级得分率%）和第48行（年级得分率%）的数据
        function createCompareAnalysisCSV(questionData) {
            let csv = '\ufeff比较分析报告\n\n';
            
            // 班级得分率%低于年级得分率%的题目
            csv += '一、班级得分率%低于年级得分率%的题目\n';
            csv += '题目名称,班级得分率(%),年级得分率(%),差距\n';
            
            for (const q of questionData.belowGradeQuestions) {
                const difference = q.gradeScoreRate - q.scoreRate;
                csv += `${q.questionName},${q.scoreRate.toFixed(2)},${q.gradeScoreRate.toFixed(2)},${difference.toFixed(2)}\n`;
            }
            
            csv += '\n';
            
            // 班级得分率最低的10道题
            csv += '二、班级得分率最低的10道题\n';
            csv += '排名,题目名称,得分率(%)\n';
            
            for (let i = 0; i < questionData.lowestScoreRateQuestions.length; i++) {
                const q = questionData.lowestScoreRateQuestions[i];
                csv += `${i + 1},${q.questionName},${q.scoreRate.toFixed(2)}%\n`;
            }
            
            return csv;
        }
        
        // 重置设置
        function resetSettings() {
            fileInput.value = '';
            fileNameEl.textContent = '未选择文件';
            headerRowInput.value = '2';
            excludedRowsInput.value = '';
            excludedRows = [];
            excludedRowContents = [];
            
            // 重置配置
            partsConfig = {
                1: {name: '第1部分', columns: [], thresholds: []},
                2: {name: '第2部分', columns: [], thresholds: []},
                3: {name: '第3部分', columns: [], thresholds: []},
                4: {name: '第4部分', columns: [], thresholds: []},
                5: {name: '第5部分', columns: [], thresholds: []},
                6: {name: '第6部分', columns: [], thresholds: []},
                7: {name: '第7部分', columns: [], thresholds: []},
                8: {name: '第8部分', columns: [], thresholds: []}
            };
            
            // 重置部分可见性
            for (let i = 5; i <= 8; i++) {
                const tab = document.querySelector(`.part-tab[data-part="${i}"]`);
                if (tab) {
                    tab.classList.add('hidden');
                }
                
                const legend = document.getElementById(`legend-part-${i}`);
                if (legend) {
                    legend.classList.add('hidden');
                }
            }
            
            // 重置当前活动部分
            currentPart = 1;
            document.querySelectorAll('.part-tab').forEach(tab => {
                tab.classList.remove('active');
            });
            document.querySelector(`.part-tab[data-part="1"]`).classList.add('active');
            
            thresholdInput.value = '';
            lastSelectedColumn = -1;
            
            // 更新已选列显示
            const selectedQuestions = document.getElementById('selectedQuestions');
            selectedQuestions.innerHTML = '<span class="help-text">请在下方表格中点击或按住Shift键点击多列进行选择</span>';
            
            // 更新部分按钮状态和预览表格
            updatePartButtons();
            updatePreview();
            
            // 重置步骤指示器
            document.getElementById('step1').classList.add('active');
            document.getElementById('step1').classList.remove('completed');
            document.getElementById('step2').classList.remove('active', 'completed');
            document.getElementById('step3').classList.remove('active', 'completed');
            
            // 隐藏区域
            configSection.classList.add('hidden');
            dataPreview.classList.add('hidden');
            actionButtons.classList.add('hidden');
            statusSection.classList.add('hidden');
            resultsSection.classList.add('hidden');
            
            fileData = null;
            fileName = '';
            
            showAlert('设置已重置', 'info');
        }
        
        // 记录状态
        function logStatus(message, type = 'info') {
            const timestamp = new Date().toLocaleTimeString();
            const statusClass = type === 'error' ? 'error' : type === 'success' ? 'success' : 'info';
            statusLog.innerHTML += `<div class="${statusClass}">[${timestamp}] ${message}</div>`;
            statusLog.scrollTop = statusLog.scrollHeight;
        }
        
        // 显示提示
        function showAlert(message, type = 'info') {
            // 先移除所有现有的警告，避免堆积
            document.querySelectorAll('.alert').forEach(alert => alert.remove());
            
            const alertDiv = document.createElement('div');
            alertDiv.className = `alert alert-${type}`;
            
            // 增强样式 - 固定在顶部
            Object.assign(alertDiv.style, {
                position: 'fixed',
                top: '10px',
                left: '50%',
                transform: 'translateX(-50%)',
                padding: '15px 25px',
                borderRadius: '8px',
                boxShadow: '0 4px 20px rgba(0,0,0,0.2)',
                zIndex: '1000',
                fontSize: '16px',
                fontWeight: type === 'error' ? 'bold' : 'normal',
                minWidth: '300px',
                textAlign: 'center',
                transition: 'opacity 0.3s ease'
            });
            
            // 设置不同类型的颜色
            if (type === 'error') {
                Object.assign(alertDiv.style, {
                    backgroundColor: '#ff4d4f',
                    color: 'white',
                    border: '2px solid #ff1a1a'
                });
            } else if (type === 'success') {
                Object.assign(alertDiv.style, {
                    backgroundColor: '#52c41a',
                    color: 'white',
                    border: '2px solid #389e0d'
                });
            } else {
                Object.assign(alertDiv.style, {
                    backgroundColor: '#1890ff',
                    color: 'white',
                    border: '2px solid #096dd9'
                });
            }
            
            let icon = 'ℹ️';
            if (type === 'error') icon = '❌';
            else if (type === 'success') icon = '✅';
            
            alertDiv.innerHTML = `<span style="margin-right: 8px; font-size: 20px;">${icon}</span><span>${message}</span>`;
            
            // 添加到body而不是main
            document.body.appendChild(alertDiv);
            
            // 错误提示持续时间更长
            const duration = type === 'error' ? 8000 : 5000;
            
            setTimeout(() => {
                alertDiv.style.opacity = '0';
                setTimeout(() => alertDiv.remove(), 300);
            }, duration);
        }
    </script>
</body>
</html>